package slistmgr

import (
	"gameserver/messages"
	"gameserver/server/Login/internal"
	"gameserver/server/Login/models"
	"sync"
	"time"

	"gitee.com/night-tc/gobige/logger"
)

/*
服务器列表管理器 ，缓存列表信息
*/
type ServerListMgr struct {

	// 缓存的服务器列表
	arealock sync.RWMutex
	areaList []*models.AreaInfo
	// 服务器列表的组信息
	groupMap map[uint64]*models.GroupInfo

	//缓存的白名单信息
	whitelock sync.RWMutex
	whitelist []*messages.Whitelist_MD
}

func NewServerListMgr() (result *ServerListMgr) {
	result = new(ServerListMgr)
	result.LoadArea()
	result.LoadWhite()
	slimgr = result
	/*
		如果login多开，那么缓存数据更新后生效时间会有1分钟左右的延迟
	*/
	internal.GetSrvinst().LoopTimer(time.Minute, func(i ...interface{}) {
		result.LoadArea()
		result.LoadWhite()
	})
	logger.Infof("ServerListMgr init")
	return
}

// 获取服务器列表
func (this *ServerListMgr) LoadArea() {
	db := internal.GetSrvinst().GetMysqlMgr()
	ali := make([]*models.AreaInfo, 0)
	if err := db.Find(&ali).Error; err != nil {
		logger.Errorf("LoadArea:%s", err)
		return
	}
	gli := make([]*models.GroupInfo, 0)
	if err := db.Find(&gli).Error; err != nil {
		logger.Errorf("LoadArea:%s", err)
		return
	}
	gmap := make(map[uint64]*models.GroupInfo)
	for _, v := range ali {
		for _, vv := range gli {
			if v.AreaID == vv.AreaID {
				vv.LoadStatus = getLoadByGroup(uint32(vv.GroupID))
				v.GroupList = append(v.GroupList, vv)
				gmap[vv.GroupID] = vv
			}
		}
	}
	this.arealock.Lock()
	defer this.arealock.Unlock()
	this.areaList = ali
	this.groupMap = gmap
}

// 获取白名单列表
func (this *ServerListMgr) LoadWhite() {
	db := internal.GetSrvinst().GetMysqlMgr()
	wli := make([]*messages.Whitelist_MD, 0)
	if err := db.Find(&wli).Error; err != nil {
		logger.Errorf("LoadWhite:%s", err)
		return
	}
	this.whitelock.Lock()
	defer this.whitelock.Unlock()
	this.whitelist = wli
}

// 获取服务器列表
func (this *ServerListMgr) GetAreaList() []*models.AreaInfo {
	this.arealock.RLock()
	defer this.arealock.RUnlock()
	return this.areaList
}

// 获取服务器信息
func (this *ServerListMgr) GetGroup(gid uint64) *models.GroupInfo {
	this.arealock.RLock()
	defer this.arealock.RUnlock()
	return this.groupMap[gid]
}

// 判断是否白名单
func (this *ServerListMgr) IsWhiteUser(userid uint64, openid, channel string, deviceid string) bool {
	this.whitelock.RLock()
	defer this.whitelock.RUnlock()
	for _, v := range this.whitelist {
		switch v.WhiteListType {
		case messages.WhiteListTypeEnum_TypeOpenID:
			if v.OpenID == openid && v.ChannelID == channel {
				return true
			}
		case messages.WhiteListTypeEnum_TypeUserID:
			if v.UserId == userid {
				return true
			}
		case messages.WhiteListTypeEnum_TypeDeviceInfo:
			if v.DeviceInfo == deviceid {
				return true
			}
		}
	}
	return false
}
